package com.hp.bon.sgw.wh.channel.handler;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.core.BuzProcessorManager;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.core.channel.SoapChannel;
import com.hp.bon.sgw.core.channel.handler.IAsynCallHandler;
import com.hp.bon.sgw.threads.TaskManager;
import com.hp.bon.sgw.wh.service.UserResourceConfigService;
import com.hp.bon.sgw.wh.util.DateUtil;
import com.hp.bon.sgw.wh.utils.LogUtil;
import com.hp.bon.sgw.wh.utils.ResultCodeUtil;
import com.hp.ocs.diameter.message.*;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.simpleframework.http.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: QueryBalanceHandle2
 * @Description: 余额查询
 */
public class QueryBalanceHandle3 implements IAsynCallHandler {
	private static final Logger _log = LoggerFactory.getLogger(QueryBalanceHandle3.class);

	private static final Object XmlMessage = null;
    private long startTime;
    private Request request;
	private PrintStream printStream;
	private JSONObject requestObject;
	private UserResourceConfigService userResourceConfigService ;
	public QueryBalanceHandle3(PrintStream printStream, JSONObject requestObject, Request request, long startTime) {
        this.startTime = startTime;
        this.request = request;
		this.printStream = printStream;
		this.requestObject = requestObject;
	}

	@Override
	public int getProtocolType() {
		return 0;
	}

	@Override
	public void onCallResult(CallParam callParam) {
        requestObject.put("jfEndTime",System.currentTimeMillis());
		XmlMessage ack = null;
		Object response = null;
		if (callParam.getResponse() != null) {
			_log.warn("getResponse():");
			response = callParam.getResponse();
		} else if (callParam.getRecvResponse() != null) {
			_log.warn("getRecvResponse():");
			response = callParam.getRecvResponse();
		}
		if (response == null) {
			int _retcodeTmp = callParam.getRetCode() == 3002 ? 11202 : callParam.getRetCode();
			ack = SoapChannel.createERRAnwser(callParam.getSessionId(), _retcodeTmp, callParam.getResultMsg());
			callParam.setServiceResultCode(_retcodeTmp);// 11203
		} else {
			if (response instanceof Message) {// CCA -> XML
				ack = BuzProcessorManager.getInstance().convertMessageToAck(callParam);
			} else if (response instanceof XmlMessage) {
				ack = (XmlMessage) response;
			} else {
				_log.warn("unknown response type:" + callParam.getResponse().getClass().getName());
			}
		}
		try {
			
			String respXML = convertResponseString(response, callParam.getServiceResultCode());

			byte[] resp = respXML.getBytes("UTF-8");
			ack.setLength(resp.length);
			ack.setMsgTime(System.currentTimeMillis());
			printStream.write(resp);
			printStream.close();
			callParam.setResponse(ack);
            //记录到日志
            LogUtil.saveLogToABM(request,respXML,startTime,requestObject);
			TaskManager.taskProcess(callParam);
            _log.info("http response(cfq) " + respXML);

		} catch (UnsupportedEncodingException e) {
			_log.info("convertResponseString UnsupportedEncodingException error,msg=" + e.getMessage());
		} catch (IOException e) {
			_log.info("convertResponseString IOException,msg=" + e.getMessage());
		}catch (Exception e) {
			e.printStackTrace();
			_log.error("convertResponseString IOException2,msg=" + e.getMessage());
		}
	}
	

	
	
	/**
	 * 返回最终json格式数据
	 * @param answer
	 * @param serviceResultCode
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private String convertResponseString(Object answer, int serviceResultCode) {
		_log.error("QueryBalanceHandle3 serviceResultCode = {}", serviceResultCode);
        _log.error("================新流程最后一步  二阶段====================");
		Gson gson = new Gson();
		// 返回json字符串最外层的map
		Map<String, Object> data = new HashMap<String, Object>();
        // 从下游解析返回信息中解析出来的数据，该数据和用户需要的数据并不相符，需要进行处理
        Map<String, Object> avpResultMap = getAvpsFromMessage((Message)answer);
		if (null == avpResultMap) {
			data.put("resultCode", "-1");
			data.put("resultMsg", "查询失败");
		}else if (serviceResultCode == 0) {
			data.put("realBalance", "");
			data.put("areaCode", requestObject.getString("areaCode"));
			data.put("queryFlag", requestObject.getString("queryFlag"));
			data.put("queryItemType", requestObject.getString("queryItemType"));
			data.put("PaymentFlag", 0);
			data.put("resultCode", "0");
			data.put("resultMsg", "SUCCESS");
			data.putAll(avpResultMap);
		}else {
			data.put("resultCode", serviceResultCode);
			data.put("resultMsg", "查询失败");
		}
        String newCode = ResultCodeUtil.updateResultCode(data.get("resultCode"), userResourceConfigService.getValue("api_resultCode"), userResourceConfigService.getValue("api_defaultResult"));
        data.put("resultCode", newCode);
        return gson.toJson(data);
		
	}

	

	/**
	 * 从返回信息中解析AVP信息
	 * @param answer
	 * @return
	 */
	public Map<String, Object> getAvpsFromMessage(Message answer) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		List<Map<String, Object>> returnPlanInfos = new ArrayList<Map<String, Object>>();
		try {
			AVP serviceINformationAVP = answer.find(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP);
			AVP_Grouped serviceInfomationGroup;
			serviceInfomationGroup = new AVP_Grouped(serviceINformationAVP);
			AVP[] avps = serviceInfomationGroup.queryAVPs();
			for(AVP avp : avps){
//				if(avp.code() == 20631 && avp.vendorID() == 81000){
//					// Result节点
//					resultMap.put("Result", String.valueOf(new AVP_Unsigned32(avp).queryValue()));
//				}
				if(avp.code() == 50104 && avp.vendorID() == 81000){
					resultMap.put("realBalance", new AVP_Integer64(avp).queryValue());
				}
				if(avp.code() == 5000 && avp.vendorID() == 81000){
					// BalanceRecordDetailInfo节点，下游返回信息中会有多个该节点
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("acctId", "");
					map.put("prodInstId", "");
					map.put("accNbr", "");
					map.put("acctBalanceId", "");
					map.put("desc", "");
					map.put("balance", "");
					map.put("available", "");
					map.put("cycleType", "");
					map.put("shareRuleFlag", "");
					map.put("used", "");
					map.put("cycleUpper", "");
					map.put("state", "");
					map.put("reserveBalance", 0);
					map.put("effDate", "");
					map.put("expDate", "");
					map.put("balanceTypeFlag", "");
					AVP_Grouped returnPlanInfoGroup = new AVP_Grouped(avp);
					AVP acctId = returnPlanInfoGroup.find(90013, Constants.DIAMETER_VENDOR_CT);
					if (acctId != null) {//Acct_ID
						map.put("acctId", Long.valueOf(new AVP_UTF8String(acctId).queryValue()));
					}
					AVP prodInstId = returnPlanInfoGroup.find(90020, Constants.DIAMETER_VENDOR_CT);
					if (prodInstId != null) {//serv_id
						map.put("prodInstId", Long.valueOf(new AVP_Unsigned64(prodInstId).queryValue()));
					}
					AVP accNbr = returnPlanInfoGroup.find(90226, Constants.DIAMETER_VENDOR_CT);
					if (accNbr != null) {//AccNbrDetail     
						map.put("accNbr", new AVP_UTF8String(accNbr).queryValue());
					}
					AVP acctBalanceId = returnPlanInfoGroup.find(50243, Constants.DIAMETER_VENDOR_CT);
					if (acctBalanceId != null) {//Acct_Balance_Id
						map.put("acctBalanceId",  Long.valueOf(new AVP_Unsigned64(acctBalanceId).queryValue()));
					}
					AVP balance = returnPlanInfoGroup.find(80165, Constants.DIAMETER_VENDOR_CT);
					if (balance != null) {//Balance     
						map.put("balance", new AVP_Integer32(balance).queryValue());
					}
					AVP available = returnPlanInfoGroup.find(50100, Constants.DIAMETER_VENDOR_CT);
					if (available != null) {//Balance_Available
						map.put("available", new AVP_Integer64(available).queryValue());
					}
					AVP cycleType = returnPlanInfoGroup.find(93076, Constants.DIAMETER_VENDOR_CT);
					if (cycleType != null) {//Cycle_Type 
						map.put("cycleType", new AVP_UTF8String(cycleType).queryValue());
					}
					AVP shareRuleFlag = returnPlanInfoGroup.find(93077, Constants.DIAMETER_VENDOR_CT);
					if (shareRuleFlag != null) {//Share_Rule_Flag
						map.put("shareRuleFlag", new AVP_Integer32(shareRuleFlag).queryValue());
					}
					AVP used = returnPlanInfoGroup.find(50101, Constants.DIAMETER_VENDOR_CT);
					if (used != null) {//Balance_Used
						map.put("used", new AVP_Integer64(used).queryValue());
					}
					AVP cycleUpper = returnPlanInfoGroup.find(93073, Constants.DIAMETER_VENDOR_CT);
					if (cycleUpper != null) {//Cycle_Upper
						map.put("cycleUpper", new AVP_Integer64(cycleUpper).queryValue());
					}
					AVP state = returnPlanInfoGroup.find(82013, Constants.DIAMETER_VENDOR_CT);
					if (state != null) {//State
						map.put("state", new AVP_UTF8String(state).queryValue());
					}
					AVP effDate = returnPlanInfoGroup.find(5021, Constants.DIAMETER_VENDOR_CT);
					if (effDate != null) {//Eff_Date
						map.put("effDate", DateUtil.dateTimeToStr(new AVP_Time(effDate).queryDate()));
					}
					AVP expDate = returnPlanInfoGroup.find(5022, Constants.DIAMETER_VENDOR_CT);
					if (expDate != null) {//Eff_Date
						map.put("expDate", DateUtil.dateTimeToStr(new AVP_Time(expDate).queryDate()));
					}
					AVP balanceTypeFlag = returnPlanInfoGroup.find(90208, Constants.DIAMETER_VENDOR_CT);
					if (balanceTypeFlag != null) {//BalanceTypeFlag
						map.put("balanceTypeFlag", new AVP_Integer32(balanceTypeFlag).queryValue()+"");
					}
					returnPlanInfos.add(map);
				}
			}
			resultMap.put("balanceQuery", returnPlanInfos);
			
		} catch (InvalidAVPLengthException e) {
			resultMap = null;
			_log.error("getAvpsFromMessage is error：", e);
		}
		return resultMap;
	}
	/**
	 * 调用详单查询webservice接口
	 * @param param
	 * @return
	 */
	private String sendWebService(String param,String url) {
		_log.info("===========WebServiceProcessor url===============" + url);
		_log.info("===========WebServiceProcessor param===============" + param);
		String resp = "";
		PostMethod post = new PostMethod(url);
		try {
			RequestEntity requestEntity = new StringRequestEntity(param, "text/xml", "UTF-8");
			post.setRequestEntity(requestEntity);
			post.setRequestHeader("SOAPAction", "text/xml; charset=utf-8");
			HttpClient client = new HttpClient();
			client.getHttpConnectionManager().getParams().setConnectionTimeout(5 * 1000);
			client.getHttpConnectionManager().getParams().setSoTimeout(5000);
			client.executeMethod(post);
			resp = post.getResponseBodyAsString();
		} catch (UnsupportedEncodingException e) {
			_log.error("===========" + url + " call UnsupportedEncodingException===============", e);
		} catch (HttpException e) {
			_log.error("===========" + url + " call HttpException===============", e);
		} catch (IOException e) {
			_log.error("===========" + url + " call IOException===============", e);
		}
		_log.info("===========WebServiceProcessor resp===============" + resp);
		return resp;
	}
	
	/**
	 * 由于计费侧提供的接口协议没变，只是地址调整，割接到3.0的本地网需要调用新的地址
	 * 集团电子发票API接口调整
	 * 获取判断使用的地址
	 * jf3_flag 刷新开关  配置为1则表示启用割接地市判断，配置为0则表示按现有的流程
	 * Jf3_jt_latn_id  割接地市配置项（多个地市用逗号分隔，如果配置项调整为888，则表示全部调用新地址）
	 * resultLanIdStr 区域编码
	 * cityId
	 * jf3_jt_latn_id 是84201这种
		jf3_latn_id是1001 1018 这种
		jf3_area_coee是027 0716 这种
		type 传参0 1001类 传1 84210类   返参 1 新 0 旧的
	 */
	private String getVersionType(String cityId,String type) {
		String jf3_flag = userResourceConfigService.getValue("jf3_flag","");////增加刷新开关  ,配置为1则表示启用割接地市判断，配置为0则表示按现有的流程
		String jf3_jt_latn_id = userResourceConfigService.getValue("jf3_jt_latn_id","");
		String jf3_latn_id = userResourceConfigService.getValue("jf3_latn_id","");
		String str;
		if("0".equals(type)) {
			//1001类型
			str = jf3_latn_id;
		}else {
			//84201 类型
			str = jf3_jt_latn_id;
		}
		//1 新流程  0 旧的流程
		if("1".equals(jf3_flag)) {
			if("888".equals(str)) {
				return "1";//新的
			}else {
				String[] split_jt_latn_id = str.split(",");
				for (String string : split_jt_latn_id) {
					if(string.equals(cityId)) {
						//包含,仅区分新旧
						return "1";//新的 Recharged.jf3@027.ctnbc-bon.net
					}
				}
			}
			
		}
		return "0";//旧的 SeverRecharge.SGWPAY@027.ctnbc-bon.net  
	}
	
	private String getAreaCode(String homeAreaCode) {
		String [][]  arr1= {{"1001","027"},{"1003","0710"},{"1004","0713"},{"1005","0717"},{"1006","0712"},
				{"1007","0711"},{"1008","0715"},{"1009","0719"},{"1010","0724"},{"1011","0714"},{"1012","0722"},
				{"1013","0718"},{"1014","0728"},{"1015","0728"},{"1016","0728"},{"1017","0719"},{"1018","0716"}};
		for (String[] strings : arr1) {
			if(homeAreaCode.equals(strings[0])) {
				return strings[1];
			}
		}
		return "027";
	}
	
	
	
	public static void main(String[] args) {
		
	}
	
}
